package com.imvc.util;

import java.io.File;
import java.io.FileReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;

/**
 * 反射工具类
 *
 * @author ml
 * @create 2017-10-18--14:20
 */
public class ReflectionUtil {

    private ReflectionUtil() {

    }

    /**
     * 通过字段名查找字段的类型
     * @param target
     * @param fieldName
     * @return
     */
    public static Class<?> getFieldType(Object target, String fieldName) {
        Class<?> clazz=target.getClass();
        String[] fs = fieldName.split("\\.");
        try {
            for(int i=0;i<fs.length-1;i++){
                Field f=clazz.getDeclaredField(fs[i]);
                target = f.getType().newInstance();
                clazz=target.getClass();
            }
            return clazz.getDeclaredField(fs[fs.length-1]).getType();
        } catch (Exception e) {
        }

        return null;
    }

    /**
     * 获取对象所有字段的名字
     * @param obj
     * @return
     */
    public static String[] getFieldNames(Object obj){
        Class<?> clazz=obj.getClass();
        Field[] fields=clazz.getDeclaredFields();
        List<String> fieldNames=new ArrayList<>();
        for (Field field : fields) {
            //获取非静态
            if ((field.getModifiers() & Modifier.STATIC) == 0) {
                fieldNames.add(field.getName());
            }
        }
        return fieldNames.toArray(new String[fieldNames.size()]);
    }

    /**
     * 通过反射取对象指定字段的值
     * @param target
     * @param fieldName
     * @return
     */
    public static Object getValue(Object target,String fieldName){
        Class<?> clazz=target.getClass();
        String[] fs=fieldName.split("\\.");
        try {
            for(int i=0;i<fs.length-1;i++){
                Field f=clazz.getDeclaredField(fs[i]);
                f.setAccessible(true);
                target=f.get(target);
                clazz=target.getClass();
            }
            Field f=clazz.getDeclaredField(fs[fs.length-1]);
            f.setAccessible(true);
            return f.get(target);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 通过反射给对象的指定字段赋值
     * @param target
     * @param fieldName
     * @param value
     */
    public static void setValue(Object target,String fieldName,Object value){
        Class<?> clazz=target.getClass();
        String[] fs=fieldName.split("\\.");
        try {
            for(int i=0;i<fs.length-1;i++){
                Field f=clazz.getDeclaredField(fs[i]);
                f.setAccessible(true);
                Object val=f.get(target);
                //还未初始化
                if(val == null){

                    Constructor<?> c=f.getType().getDeclaredConstructor();
                    c.setAccessible(true);
                    val=c.newInstance();
                    f.set(target,val);
                }
                target=val;
                clazz=target.getClass();

            }

            Field f=clazz.getDeclaredField(fs[fs.length-1]);
            f.setAccessible(true);
            f.set(target,value);
        } catch (Exception e) {
           throw new RuntimeException(e);
        }
    }
}
